#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QComboBox"
#include "QDebug"
#include "QProgressBar"
#include "QLabel"
#include "QFont"
#include "QApplication"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

  //openAction = new QAction(QIcon(":/images/doc-open"), "打开", this);

  //openAction->setShortcuts(QKeySequence::Open);
    //openAction->setStatusTip(tr("Open an existing file"));
  //  connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

  //  menuBar()->addMenu(tr("&SS"));
   // file->addAction(openAction);

    //QToolBar *toolBar = addToolBar(tr("&File"));
  //  toolBar->addAction(openAction);

    this->setFixedSize( this->width (),this->height ());
    QObject::connect(&TIME1, &QTimer::timeout, this, &MainWindow::timer_slots_IRQHandler);
    QObject::connect(&TIME2, &QTimer::timeout, this, &MainWindow::timer2_slots_IRQHandler);
    QObject::connect(&serial, &QSerialPort::readyRead, this, &MainWindow::serial_slots_IRQHandler);
    QObject::connect(this, &MainWindow::pack_Send, this, &MainWindow::on_file_send_boutton_clicked);   
    QObject::connect(this, &MainWindow::send_signals_serial_data_handle, this, &MainWindow::signal_serial_data_handler);
    TIME2.start(30);

    app_uart_init();


}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::parInit(void)
{
    this->Ota_updata_step = 0;
    this->file_pack_mod = 0;  //包的模
    this->file_pack_rem =0; //包的余数
    this->file_pack_num =0; //总包数

}

void MainWindow::on_uart_button_clicked()
{
    QString uart_botton_text = ui->uart_button->text();

     if(uart_botton_text=="打开串口")  // 串口处于关闭状态
     {
        serial.setFlowControl(QSerialPort::NoFlowControl);    //设置串口流
        bool serial_state = serial.open(QIODevice::ReadWrite);//串口设置位读写
        if(serial_state ==false)
        {
            ui->textBrowser->append(tr("串口号被占用"));
        }
        else
        {
             ui->textBrowser->append(tr("串口打开成功!"));
             ui->uart_button->setText(tr("关闭串口"));
        }
     }
     else
     {
        ui->uart_button->setText(tr("打开串口"));
        ui->textBrowser->append(tr("关闭串口成功!"));
        serial.close();
        this->parInit();
        ui->file_send_boutton->setEnabled(true);
     }
}

void MainWindow::on_com_Box_currentIndexChanged(int index)
{
    Q_UNUSED(index);

    int current_index = ui->com_Box->currentIndex();  //获取当前下拉菜单的第几个项目
    QString com_Box_text = ui->com_Box->itemText(current_index);//获取当前项目的名称

    qDebug() << "当前串口为:" << com_Box_text << endl;

    serial.setPortName(com_Box_text);   //获取串口名
    ui->uart_button->setText("打开串口");  // 按钮显示字符
    serial.close();  // 默认关闭

}


void MainWindow::on_band_Box_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    int current_index = ui->band_Box->currentIndex();  //获取当前在第几个项目
    QString band_Box_text = ui->band_Box->itemText(current_index);//获取当前在第几个项目的名称

    if(band_Box_text=="2400")
    {
        serial.setBaudRate(QSerialPort::Baud2400);
        qDebug("波特率设置2400成功");
    }
    else if(band_Box_text=="4800")
    {
        serial.setBaudRate(QSerialPort::Baud4800);
        qDebug("波特率设置4800成功");
    }
    else if(band_Box_text=="9600")
    {
        serial.setBaudRate(QSerialPort::Baud9600);
        qDebug("波特率设置9600成功");
    }
    else if(band_Box_text=="19200")
    {
        serial.setBaudRate(QSerialPort::Baud19200);
        qDebug("波特率设置19200成功");
    }
}

void MainWindow::on_checkBit_Box_currentIndexChanged(int index)
{
    Q_UNUSED(index);

    int current_index = ui->checkBit_Box->currentIndex();  //获取当前在第几个项目
    QString checkBit_Box_text = ui->checkBit_Box->itemText(current_index);//获取当前在第几个项目的名称
    if(checkBit_Box_text=="偶校验")
    {
         serial.setParity(QSerialPort::EvenParity);//设置偶校验
         qDebug("设置偶校验OK");
    }
    else if(checkBit_Box_text =="奇校验")
    {
         serial.setParity(QSerialPort::OddParity);//设置奇偶校验
         qDebug("设置奇校验OK");
    }
    else if(checkBit_Box_text== "无校验")
    {
        serial.setParity(QSerialPort::NoParity);//设置
        qDebug("设置无校验OK");
    }
}

void MainWindow::on_dataBit_Box_currentIndexChanged(int index)
{
    Q_UNUSED(index);
    int current_index = ui->dataBit_Box->currentIndex();  //获取当前在第几个项目
    QString dataBit_Box_text = ui->dataBit_Box->itemText(current_index);//获取当前在第几个项目的名称
    if(dataBit_Box_text=="7")
    {
       serial.setDataBits(QSerialPort::Data7); //设置数据位数
       qDebug("数据位数7设置");
    }
    else
    {
        serial.setDataBits(QSerialPort::Data8);
        qDebug("数据位数8设置");
    }
}



void MainWindow::on_stopBit_Box_currentIndexChanged(int index)
{
    Q_UNUSED(index);

    int current_index = ui->stopBit_Box->currentIndex();  //获取当前在第几个项目
    QString stopBit_Box_text = ui->stopBit_Box->itemText(current_index);//获取当前在第几个项目的名称
    if(stopBit_Box_text=="7")
    {
       serial.setStopBits(QSerialPort::OneStop);
       qDebug("设置1位停止位");
    }
    else
    {
       serial.setStopBits(QSerialPort::TwoStop);
       qDebug("设置2位停止位");
    }
}











//函数:打开一个文件路径，得到文件得大小

void MainWindow::on_file_down_clicked()
{

    QString path =QFileDialog::getOpenFileName(this, tr("Open File"),
                                                "../",
                                                tr("Text files (*.bin)"));

    if(path.isEmpty() ==false)
    {
       ui->pathTxT->setText(path);   //显示路径到框中

       QFile file(path); //定于一个对象
       bool isok = file.open(QIODevice::ReadOnly); //打开文件路径下的文件
       if(isok == true)
       {
          this->file_datebuff = file.readAll(); //读取文件中的内容
          this->file_data_Size = file_datebuff.size();
          file.close();//取出来后关闭文件

          file_pack_mod = this->file_data_Size /128;
          file_pack_rem = this->file_data_Size %128;
          if(file_pack_rem!=0)
          {
              file_pack_num = file_pack_mod+1;
              file_datebuff.append(128-file_pack_rem,0);
          }

          MD5_BUF= QCryptographicHash::hash(this->file_datebuff, QCryptographicHash::Md5);

          ui->progressBar->setValue(0);

          QString str = QString("文件加载成功, size = %1").arg(this->file_data_Size);
          ui->textBrowser->append(str);
          qDebug()<<"MD5校验为"<<MD5_BUF.toHex();
       }
    }

}


void MainWindow::on_file_send_boutton_clicked()
{
    QByteArray s_buff_hex;
    unsigned char index =0;
    unsigned char crc =0;
    unsigned char i=0;

    s_buff_hex.resize(200);
    s_buff_hex[index++]=0x68;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x99;
    s_buff_hex[index++]=0x68;

    if(serial.isOpen())
    {

       if(this->Ota_updata_step ==0)  //初始化
       {

           s_buff_hex[index++] =0x33;
           s_buff_hex[index++] =0x01;
           s_buff_hex[index++] =0x03;
           file_data_readIndex =0;  //读光标置0
           ui->file_send_boutton->setDisabled(true);

       }

       else if(this->Ota_updata_step ==1)
       {
            qDebug()<<"启动发送升级包";
            s_buff_hex[index++]=0x32;
            s_buff_hex[index++]=0X84;
            s_buff_hex[index++] = this->file_pack_num %256;
            s_buff_hex[index++] = this->file_pack_num /256;

            s_buff_hex[index++] = (file_data_readIndex+1) %256;
            s_buff_hex[index++] = (file_data_readIndex+1) /256;

            if(this->OTA_Pack_Send_Mode==0) //常规发包
            {

               if(file_data_readIndex <=file_pack_mod)
               {
                   int per =file_data_readIndex*100/file_pack_mod;

                    ui->progressBar->setValue(per);
                   for(i=0;i<128;i++)
                   {
                      s_buff_hex[index+i] = this->file_datebuff[file_data_readIndex*128+i];
                   }

                   index+=128;
                   this->file_data_readIndex++;
                   qDebug()<< "已发包数:"<<file_data_readIndex<<"总包数:"<<file_pack_num<<endl;
               }

            }
            else { //说明是补发包

               if(pack_rx_state.size()!=0)
               {
                    file_data_readIndex = (uint8_t)pack_rx_state.at(0)-1;
                    for(i=0;i<128;i++)
                    {
                        s_buff_hex[index+i] = (uint8_t)this->file_datebuff[file_data_readIndex*128+i];
                    }
                    index+=128;
                    qDebug()<< "已发补包号:"<< pack_rx_state.toHex()<<"剩余包数:"<< pack_rx_state.size()<<endl;
                    pack_rx_state.remove(0,1);

               }

            }
       }
       else if(this->Ota_updata_step == 2)
       {
            s_buff_hex[index++]=0x33;
            s_buff_hex[index++]=0x1;
            s_buff_hex[index++]=0x1;
       }
       else if(this->Ota_updata_step == 3)
       {
               s_buff_hex[index++]=0x33;
               s_buff_hex[index++]=24;
               s_buff_hex[index++]=0x02;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
               s_buff_hex[index++]=0;
              for(uint8_t cnt=0;cnt<16;cnt++)
              {
                   s_buff_hex[index+cnt] = MD5_BUF.at(cnt);
              }
              index+=16;
       }

       crc = mytool::cal_crc8(s_buff_hex,index);
       s_buff_hex[index++] =crc;
       s_buff_hex[index++] =0x16;
       serial.write(s_buff_hex,index);
       TIME1.start(250);   //开启定时器延迟2秒

    }
    else
    {
         qDebug("串口未被打开!");
         //emit pack_Send();
    }

}



void MainWindow::signal_serial_data_handler()
{

    QByteArray rx_buff;
    unsigned char crc;
    unsigned char lv_after_num;

    rx_buff.resize(100);

    if(serial_RX_BUFF.size()>13)
    {
          // this->serial_RX_BUFF=  this->serial_RX_BUFF.right(this->serial_RX_BUFF.length()-this->serial_RX_BUFF.indexOf('\xff')-1);

           lv_after_num = mytool::APP_FrameCMD_Strip(this->serial_RX_BUFF,this->serial_RX_BUFF.size(),rx_buff);
           crc = mytool::cal_crc8(rx_buff,lv_after_num-2);

           if(crc==(unsigned char )(rx_buff.at(lv_after_num-2)))
           {
              qDebug()<< "crc校验为"<<crc<<"  校验通过"<<endl;
              if(rx_buff.at(8)=='\x91' && (this->Ota_updata_step ==0) && rx_buff.at(10)=='\x01')  //功能码
              {
                    QByteArray ver = rx_buff.mid(14,5);
                  //   QString b =  a.toStdString();
                    QString str = QString(ver);
                    QString str_text = QString("软件版本号 :  %1").arg(str);
                    ui->textBrowser->append(str_text);

              }

              if(rx_buff.at(8)==0x33)  //功能码
              {
                   if(rx_buff.at(10)==0x01 && (this->Ota_updata_step ==2))  //接收到了相应包的回复
                   {
                       // qDebug()<<"成功收到设备的包回复"<<endl;
                        TIME1.stop(); //停止定时器
                        unsigned int  success_rx_pack_num =((unsigned char)rx_buff.at(9))*256+ ((unsigned char)rx_buff.at(10)) ;//成功接收到的总包数
                        qDebug()<< "成功接收到的总包数为："<< success_rx_pack_num<<endl;

                        uint16_t bytes_mod = file_pack_num/8;
                        uint16_t bytes_rem = file_pack_num%8;

                        uint16_t _bytes = bytes_mod;
                         if(bytes_rem!=0)
                         {
                             _bytes+=1;
                         }

                         for(uint16_t i=0; i<_bytes;i++)
                         {
                             uint16_t bit=0;
                             if((_bytes-1)==i)
                             {
                                if(bytes_rem!=0)
                                  bit = bytes_rem;
                                else {
                                  bit = 8;
                                }
                             }
                             else
                             {
                                bit = 8;
                             }

                             for(uint16_t k=0; k<bit;k++)
                             {
                                 uint8_t is_ok = ( (uint8_t)(rx_buff.at(lv_after_num-3-i))>>(k))&0x01;

                                  if(is_ok==0)
                                  {
                                      this->pack_rx_state.append(i*8+(k+1));
                                      qDebug()<<i*8+(k+1);
                                  }
                             }

                         }

                       qDebug()<<"丢包个数："<<this->pack_rx_state.size();

                       if(pack_rx_state.size()!=0) //不等于0，说明
                       {
                           this->Ota_updata_step = 1; //重新到达，发送包状态；
                           this->OTA_Pack_Send_Mode=1; //模式切换为1
                           ui->textBrowser->append(tr("包丢失正在补发中，请稍后......"));
                           emit pack_Send();
                       }
                       else
                       {
                           this->Ota_updata_step =3;
                           emit pack_Send();
                           //qDebug()<<"包完整，准备发送MD5校验"<<pack_rx_state.size();
                           ui->textBrowser->append("包接收完整, 软件升级成功!");
                           ui->file_send_boutton->setEnabled(true);
                       }
                   }
                   else if(rx_buff.at(10)==0x03 && this->Ota_updata_step  ==0) //判断是否是初始化得回复
                   {
                        TIME1.stop(); //停止定时器
                        this->Ota_updata_step=1;
                        emit pack_Send();
                        ui->textBrowser->append("初始化成功!");
                   }
                   else if(rx_buff.at(10)==0x02 && this->Ota_updata_step ==3)//校验回复成功
                   {
                         ui->textBrowser->append("软件升级成功!");
                         this->parInit();
                   }

              }
           }
           serial_RX_BUFF.clear();
     }

}


/*
 * 定时器1 槽函数
 *
 *
 */
void MainWindow::timer_slots_IRQHandler()
{
  if(this->timeout<0xffff)
    this->timeout++;
  if( this->timeout>10)
   {
      this->timeout =0;
      TIME1.stop();
      if(this->Ota_updata_step==0)
      {
         ui->textBrowser->append("初始化失败，已中止传输" );
         ui->file_send_boutton->setEnabled(true);
      }
      else if(this->Ota_updata_step==1)
      {
          if(this->OTA_Pack_Send_Mode==0) //正常模式下
          {
              if(file_data_readIndex<=file_pack_mod)
              {
                 emit pack_Send();
              }
              else
              {
                  qDebug()<<"数据包发送完成，准备查询包状态"<<endl;
                  this->Ota_updata_step=2;
                  emit pack_Send();
              }
          }
          else
          {
                if(pack_rx_state.size()!=0)
                {
                    emit pack_Send();
                }
                else {
                    qDebug()<<"补发发送完成，准备查询包状态"<<endl;
                    this->Ota_updata_step=2;
                }

          }

      }

     // qDebug()<< serial_RX_BUFF<<"定时器已经被关闭"; //打印
      serial_RX_BUFF.clear();
   }
}

void MainWindow::timer2_slots_IRQHandler()
{
  if(this->time2_sertal_cnt<0xffff)
  {
      this->time2_sertal_cnt++;
      if(this->time2_sertal_cnt>5 && (this->serial_RX_BUFF.size())>13)
      {
         //ui->textBrowser->append(tr(this->serial_RX_BUFF.toHex()));
          emit send_signals_serial_data_handle();

         // QString  str =  QString("%1").arg(this->serial_RX_BUFF);


      }

  }
}


void MainWindow::serial_slots_IRQHandler()
{

  this->serial_RX_BUFF.append(serial.readAll());
  this->time2_sertal_cnt =0;

/*
    if (serial.waitForReadyRead(20))
    {
      QByteArray responseData = serial.readAll();
      while (1)
      {
          if(serial.waitForReadyRead(30)==false)
          {
              qDebug() << responseData;
          }
          else {
              responseData += serial.readAll();
          }
          QApplication::processEvents();
      }
    }

*/
}

void MainWindow::on_actioninformation_triggered()
{
    QLabel *lab = new QLabel(0);

    QFont  font ( "Microsoft YaHei",11,75);
    lab->setGeometry(100,100,200,100);
    lab->setText("version_1_0");
    lab->setFont(font);
    lab->show();


}




void MainWindow::on_getMCUVersion_clicked()
{
    QByteArray s_buff;
    unsigned char index =0;
    unsigned char crc =0;
    s_buff.resize(30);
    s_buff[index++]=0x68;
    s_buff[index++]=0x99;
    s_buff[index++]=0x99;
    s_buff[index++]=0x99;
    s_buff[index++]=0x99;
    s_buff[index++]=0x99;
    s_buff[index++]=0x99;
    s_buff[index++]=0x68;
    s_buff[index++]=0x11;
    s_buff[index++]=0x04;
    s_buff[index++]=0x01;
    s_buff[index++]=0x00;
    s_buff[index++]=0x80;
    s_buff[index++]=0x04;


    if(serial.isOpen())
    {
        crc = mytool::cal_crc8(s_buff,index);
        s_buff[index++] =crc;
        s_buff[index++] =0x16;
        serial.write(s_buff,index);
    }
    else {
        ui->textBrowser->append("串口未打开!");
    }

}


void MainWindow::on_ClearLog_clicked()
{
    ui->textBrowser->clear();
}

